package com.hbuzzs.elasticsearch.util;

import cn.hutool.core.util.StrUtil;
import lombok.extern.slf4j.Slf4j;
import org.elasticsearch.index.query.*;
import org.springframework.context.annotation.Configuration;

import java.util.concurrent.atomic.AtomicInteger;

/**
 * @Description ES工具
 * @Author zhangzhishun
 * @Date 2020/12/8-16:10
 */
@Slf4j
@Configuration
public class ElasticsearchUtil {

    /**
     * 输出ES查询的参数
     *
     * @param queryBuilders es查询条件
     */
    public static void printParam(BoolQueryBuilder queryBuilders) {
        String sql = printBoolQueryBuilder(queryBuilders);
        log.info("条件 : {}", sql.length() == 0 ? "无条件" : sql);
    }

    /**
     * 输出BoolQueryBuilder条件为sql条件
     * */
    private static String printBoolQueryBuilder(BoolQueryBuilder boolQueryBuilder) {
        StringBuilder sql = new StringBuilder();
        // or
        AtomicInteger shouldCount = new AtomicInteger(0);
        if (boolQueryBuilder.should().size() > 0) {
            sql.append(" ( ");
        }
        boolQueryBuilder.should().forEach(e -> {
            if (shouldCount.get() > 0) {
                sql.append(" OR ");
            }
            String shouldToSql = convertToSql(e);
            sql.append(shouldToSql);
            if (shouldToSql.length() > 0) {
                shouldCount.incrementAndGet();
            }
        });
        if (boolQueryBuilder.should().size() > 0) {
            sql.append(" ) ");
        }
        // and
        AtomicInteger filterCount = new AtomicInteger(0);
        boolQueryBuilder.filter().forEach(e -> {
            if (filterCount.get() > 0) {
                sql.append(" AND ");
            }
            String filterToSql = convertToSql(e);
            sql.append(filterToSql);
            if (filterToSql.length() > 0) {
                filterCount.incrementAndGet();
            }
        });
        boolQueryBuilder.must().forEach(e -> {
            log.error("queryBuilders.must()未处理，但已经出现该情况：{}", e);
            sql.append(convertToSql(e));
        });
        // !=
        boolQueryBuilder.mustNot().forEach(e -> {
            log.error("queryBuilders.mustNot()未处理，但已经出现该情况：{}", e);
            sql.append(convertToSql(e));
        });
        return sql.toString();
    }

    /**
     * 一个条件 比如 a = 1
     */
    private static String convertToSql(QueryBuilder queryBuilder) {
        StringBuilder sql = new StringBuilder();
        // 如果是BoolQueryBuilder递归转换
        if (queryBuilder instanceof BoolQueryBuilder) {
            sql.append(printBoolQueryBuilder((BoolQueryBuilder) queryBuilder));
        } else if (queryBuilder instanceof TermQueryBuilder) {
            // =
            String key = ((TermQueryBuilder) queryBuilder).fieldName();
            String value = ((TermQueryBuilder) queryBuilder).value().toString();
            sql.append(key);
            sql.append(" = ");
            sql.append(value);
        } else if (queryBuilder instanceof RangeQueryBuilder) {
            // 范围
            String key = ((RangeQueryBuilder) queryBuilder).fieldName();
            Object from = ((RangeQueryBuilder) queryBuilder).from();
            Object to = ((RangeQueryBuilder) queryBuilder).to();
            if (from != null && !StrUtil.isEmpty(from.toString())) {
                sql.append(key);
                sql.append(" >= ");
                sql.append(from.toString());
            }
            if (to != null && !StrUtil.isEmpty(to.toString())) {
                if (from != null && !StrUtil.isEmpty(from.toString())) {
                    sql.append(" AND ");
                }
                sql.append(key);
                sql.append(" <= ");
                sql.append(to.toString());
            }
        } else if (queryBuilder instanceof WildcardQueryBuilder) {
            // 模糊查询
            String key = ((WildcardQueryBuilder) queryBuilder).fieldName();
            String value = ((WildcardQueryBuilder) queryBuilder).value();
            sql.append(key);
            sql.append(" LIKE '");
            if (value.charAt(0) == '*') {
                value = value.replaceFirst("\\*", "%");
            }
            if (value.charAt(value.length() - 1) == '*') {
                value = replaceLast(value, "\\*", "%");
            }
            sql.append(value);
            sql.append("' ");
        } else {
            log.error("{}函数缺少处理:{}", "convertToSql", queryBuilder);
        }
        return sql.toString();
    }


    /**
     * 替换字符串里最后出现的元素
     *
     * @param text 被替换的字符串
     * @param var1 被替换的字符
     * @param var2 替换后的字符
     */
    private static String replaceLast(String text, String var1, String var2) {
        return text.replaceFirst("(?s)" + var1 + "(?!.*?" + var1 + ")", var2);
    }

}